- environment : local jupyter lab
- 앞에서 주어진 데이터로 모델을 돌려봤으니까 이제 우리 데이터로 모델을 학습하고 돌려보자.
- 해야할 것 : 데이터 로드 함수, 데이터 폴더, 예측 함수 수정
import
Code
#!pip install pafy youtube-dl moviepy
#!pip install pytube
#!pip install opencv-python
import random
import time
import math
import numpy as np
import torch
import os
import cv2
import torchvision
from moviepy.editor import *
from collections import deque
import sys
- 경로 추가
- 경로 추가해도 안되니 걍 해당 파일을 현재 작업 경로에 넣어 두자
- 사용자 정의 .py 파일 import
#!pip install --user albumentations
import Fight_utils
from Fight_utils import *
Fine Tuning and Training
Code
seed_constant = 70
np.random.seed(seed_constant)
random.seed(seed_constant)
torch.manual_seed(seed_constant)
torch.cuda.manual_seed_all(seed_constant)
사전학습된 모델 로드
model_ft = torchvision.models.video.mc3_18(pretrained=True, progress=True)
- 인풋, 아웃풋 피처별 선형 레이어 생성
num_ftrs = model_ft.fc.in_features #
model_ft.fc = torch.nn.Linear(num_ftrs, 2) #nn.Linear(in_features, out_features)
샘플 데이터셋 로드
- 일단 임의로 넣어둔 20개 데이터로만 학습하자.
- 흠…로컬에서는 경로 설정이 조금 빡세다….
DATASET_DIR = 'D:\projects\mysite2\posts\DX\BP\Fight_Detection_From_Surveillance_Cameras-PyTorch_Project\dataset' ## 데이터셋 경로 설정
CLASSES_LIST = ['fall','Fight'] ## 폴더이름하고 동일한
SEQUENCE_LENGTH = 16
batch_size= 4
x_tensor, y_tensor=Fight_utils.create_dataset(DATASET_DIR,CLASSES_LIST,SEQUENCE_LENGTH)
Extracting Data of Class: fall
Extracting Data of Class: Fight
x_tensor.shape, y_tensor.shape
(torch.Size([40, 3, 16, 112, 112]), torch.Size([40]))
np.unique(y_tensor, return_counts = True)
(array([0, 1], dtype=int64), array([20, 20], dtype=int64))
device 셋팅
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
device
데이터셋 분할
x_tensor, y_tensor = x_tensor.to(device), y_tensor.to(device)
dataset = torch.utils.data.TensorDataset(x_tensor, y_tensor) # 입력 데이터와 해당하는 레이블을 함께 저장
val_size = int(len(dataset)*0.3) ##
train_size = len(dataset)- int(len(dataset)*0.3)
train_dataset, test_val_dataset = torch.utils.data.random_split(dataset, [train_size, val_size])
val_size = int(len(test_val_dataset)*0.5)
test_size = len(test_val_dataset)- int(len(test_val_dataset)*0.5)
val_dataset, test_dataset = torch.utils.data.random_split(test_val_dataset, [val_size, test_size])
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
val_loader = torch.utils.data.DataLoader(dataset=val_dataset, batch_size=batch_size, shuffle=True)
dataloaders_dict = {'train':train_loader,'val':val_loader }
# To empty the Memory
torch.cuda.empty_cache()
모델 학습
# 모델 GPU에 올리기
model_ft = model_ft.to(device)
# 에포크 설정
epochs = 5
# Loss Function 설정
criterion = torch.nn.CrossEntropyLoss()
# Optimization Function (SGD-----> Stocastic Gradient Descent)
optimizer_ft = torch.optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9)
model_ft, hist = Fight_utils.train_model(device,model_ft, dataloaders_dict, criterion, optimizer_ft, num_epochs=epochs)
Epoch 0/4
----------
train Loss: 0.3590 Acc: 0.8214
val Loss: 0.0717 Acc: 1.0000
Epoch 1/4
----------
train Loss: 0.3617 Acc: 0.7857
val Loss: 0.0303 Acc: 1.0000
Epoch 2/4
----------
train Loss: 0.3411 Acc: 0.7143
val Loss: 0.0488 Acc: 1.0000
Epoch 3/4
----------
train Loss: 0.1391 Acc: 1.0000
val Loss: 0.0341 Acc: 1.0000
Epoch 4/4
----------
train Loss: 0.3958 Acc: 0.7500
val Loss: 0.0256 Acc: 1.0000
Training complete in 2m 33s
Best val Acc: 1.000000
test 데이터 예측
since = time.time()
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=True) ## test 데이터를 배치단위로 쪼갬
model_ft.eval() ## 평가모드로 전환
running_loss = 0.0 ## loss값 초기
running_corrects = 0
y_test = []
y_pred = []
for inputs, labels in test_loader:
inputs = inputs.to(device)
labels = labels.to(device)
optimizer_ft.zero_grad()
with torch.set_grad_enabled(False):
outputs = model_ft(inputs)
loss = criterion(outputs, labels)
_, preds = torch.max(outputs, 1)
running_loss += loss.item() * inputs.size(0)
running_corrects += torch.sum(preds == labels.data)
y_test += labels.data.tolist()
y_pred += preds.data.tolist()
epoch_loss = running_loss / len(test_loader.dataset)
epoch_acc = running_corrects.double() / len(test_loader.dataset)
time_elapsed = time.time() - since
print('완료 시간 : {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))
print('Loss: {:.4f} Acc: {:.4f}'.format(epoch_loss, epoch_acc))
완료 시간 : 0m 2s
Loss: 0.0779 Acc: 1.0000
from sklearn.metrics import *
cf_matrix = confusion_matrix(y_test, y_pred)
print(cf_matrix)
print(classification_report(y_test, y_pred))
precision recall f1-score support
0 1.00 1.00 1.00 1
1 1.00 1.00 1.00 5
accuracy 1.00 6
macro avg 1.00 1.00 1.00 6
weighted avg 1.00 1.00 1.00 6
model save & load & predict
save
PATH = "D:/projects/mysite2/posts/DX/BP/model_save/test_model1.pth"
torch.save(model_ft.state_dict(), PATH)
load
model_ft = torchvision.models.video.mc3_18(pretrained=True, progress=True)
num_ftrs = model_ft.fc.in_features
model_ft.fc = torch.nn.Linear(num_ftrs, 2)
model_ft.load_state_dict(torch.load(PATH))
model_ft = model_ft.to(device)
#model_ft.eval()
원본비디오 재생
os.listdir("D:/projects/mysite2/posts/DX/BP/test video/폭행")
['폭행29.mp4', '폭행30.mp4', '폭행31.mp4', '폭행32.mp4', '폭행33.mp4']
path_output = "D:/projects/mysite2/posts/DX/BP/test video/폭행/폭행31.mp4"
Fight_utils.show_video(path_output, width=960)
비디오 클래스 추정
path_1 = "D:/projects/mysite2/posts/DX/BP/test video/폭행/폭행31.mp4"
path_2 = "D:/projects/mysite2/posts/DX/BP/test video/실신/실신19.mp4"
- 슈발 함수 수정하고 restart 하니까 된다…
print(Fight_utils.FightInference(path_1,model_ft,SEQUENCE_LENGTH))
print(Fight_utils.FightInference_Time(path_1, model_ft, SEQUENCE_LENGTH)) ## 추론하는데 걸린시간
fight
[('fight', 0.60055), ('fall', 0.39945)]
***********
time is: 2.789564371109009
fight
클래스 추정 후 비디오 표시
import Fight_utils
from Fight_utils import *
output_path = "D:/projects/mysite2/posts/DX/BP/test video/output/result1.mp4"
start_time = time.time()
outVideo_1=Fight_utils.showIference(model_ft, 16, 2, path_1, output_path, showInfo = False)
elapsed = time.time() - start_time
print("time is:",elapsed)
VideoFileClip(outVideo_1, audio=False, target_resolution=(300,None)).ipython_display()
Moviepy - Building video __temp__.mp4.
Moviepy - Writing video __temp__.mp4
Moviepy - Done !
Moviepy - video ready __temp__.mp4